home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 3660 < prev    next >
Encoding:
Internet Message Format  |  1996-08-06  |  5.9 KB

  1. Path: news.clark.net!usenet
  2. From: gusty@clark.net (Harlan Messinger)
  3. Newsgroups: comp.lang.java,comp.lang.c,comp.lang.c++
  4. Subject: Re: Correct mod/rem (was: Problem with % (remainder) operator
  5. Date: Thu, 25 Jan 1996 03:58:34 GMT
  6. Organization: Clark Internet Services, Inc.
  7. Message-ID: <4e6v4c$1ct@clarknet.clark.net>
  8. References: <4dc86s$gha@news.xs4all.nl> <4d8hnd$74h@news.xs4all.nl> <443322587wnr@almide.demon.co.uk> <142091149wnr@almide.demon.co.uk> <4dguci$le3@news.ox.ac.uk> <hbaker-2201961022380001@10.0.2.15>
  9. NNTP-Posting-Host: gusty-ppp.clark.net
  10. Mime-Version: 1.0
  11. Content-Type: TEXT/PLAIN; charset=ISO-8859-1
  12. Content-Transfer-Encoding: 8bit
  13. X-Newsreader: Forte Free Agent 1.0.82
  14.  
  15. I apologize for my previous answer--I misread something Mr. Baker had
  16. written. He came to the same conclusion as I for positive divisors.
  17.  
  18. Never mind.
  19.  
  20. Harlan Messinger
  21.  
  22. hbaker@netcom.com (Henry Baker) wrote:
  23.  
  24. >This problem has been discussed ad nauseum in every single comp.lang
  25. >newsgroup, and it seems to be that every language gets it wrong in the
  26. >first n iterations, so that the implementers of the new languages keep
  27. >copying the wrong code from their previous language.
  28.  
  29. >The usual justification for getting it wrong is that 'that's what the
  30. >hardware does, and we want fast code'.  Of course, once the language gets
  31. >established and _portability_ to a wide variety of machines becomes important,
  32. >it becomes necessary to try to retrofit a fully specified function, thus
  33. >breaking many existing programs.
  34.  
  35. >So far as I know, only APL and Common Lisp have attempted to get 'mod' right.
  36.  
  37. >'Everybody' thinks they know how division works, because they all learned it
  38. >in graded school.
  39.  
  40. >OK, so what did you learn?  Given a 'dividend' N and a 'divisor' D, we need
  41. >to compute a 'quotient' Q, and a 'remainder' R.  What properties do we want
  42. >from this quotient Q and this remainder R?
  43.  
  44. >The first property is that N = Q*D + R.  Otherwise, the whole meaning of
  45. >'remainder' is lost -- i.e., that part that 'remains' after taking out Q
  46. >copies of D from N.
  47.  
  48. >Fine, so we simply set Q=0, R=N.  'You can't do that," you say.  Why?  Because
  49. >then division didn't _do_ anything, it didn't make R 'small'.
  50.  
  51. >Why do we need R 'small'?  Well, if we're converting binary to decimal, and
  52. >we divide our binary number by 10 and get as a remainder our original binary
  53. >number, we will need an awful lot of decimal 'digits' :-).  So, using base
  54. >conversion as a _criterion_, we add the additional constraint that
  55.  
  56. >0 <= |R| < |D|.
  57.  
  58. >In other words, we want the absolute value of the 'remainder' to be smaller
  59. >than the absolute value of the divisor.
  60.  
  61. >However, this still doesn't pin down the answer.  For example, if we divide
  62. >27 by 10, we can get two different quotients and remainders:
  63.  
  64. >(I)     27 = 2*10 + 7         i.e., Q=2, R=7
  65.  
  66. >(II)    27 = 3*10 + (-3)      i.e., Q=3, R=-3
  67.  
  68. >Going back to our decimal conversion problem again, we decide that the
  69. >most appropriate choice is the first, not the second, since we want base
  70. >conversion to 'work' correctly.
  71.  
  72. >We therefore refine our constraints, but find that we still have two choices
  73. >when the divisor is _negative_.
  74.  
  75. >(I)     0 <= R < |D|
  76.  
  77. >(II)    0 <= R*D < D^2
  78.  
  79. >For example, if we divide 27 by -10, we can still get two different quotients
  80. >and remainders:
  81.  
  82. >(I)     27 = (-2)*(-10) + 7     i.e., Q=-2, R=7
  83.  
  84. >(II)    27 = (-3)*(-10) + (-3)  i.e., Q=-3, R=-3
  85.  
  86. >Once again, we appeal to the base conversion algorithm for our answer.  In
  87. >the case of a negative divisor, we _expect_ negative digits -- indeed, we
  88. >_demand_ them, so that the correct choice is (II), which can be expressed
  89. >by the rule "sign of remainder follows sign of the divisor" (NOT, sign of
  90. >the dividend, like lots of brain-damaged computer hardware).
  91.  
  92. >The nice thing about the "sign of the divisor" choice is that the quotient
  93. >is easily expressed as the 'floor' function:  Q = floor[N/D].
  94.  
  95. >----
  96.  
  97. >There is another division function called 'round' which tries to find the
  98. >'closest' integer to the rational quotient.  As might be expected, the
  99. >remainders produced by 'round' are smaller than those produced by 'floor',
  100. >and are both positive and negative:
  101.  
  102. >0 <= |R| <= |D|/2
  103.  
  104. >This is well-defined if D is an odd integer, but is ambiguous if D is even.
  105. >There are several competing definitions for what to do if D is even: one of
  106. >them is 'if N/D falls half way between two integers, choose the even one
  107. >as the quotient'.  This rule is similar to one that is used by numerical
  108. >analysts as an 'unbiased' rounding rule, and is used by some IEEE float
  109. >implementations.
  110.  
  111. >Base conversion sometimes uses remainders produced by 'round' instead of
  112. >'floor'.  For example, hardware multipliers often convert to a 'balanced'
  113. >notation.  If we were doing decimal, then we would use the 'digits'
  114. >-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, instead of 5, 6, 7, 8, 9, 0, 1, 2, 3, 4,
  115. >respectively, because it reduces the number of carries that have to propagate.
  116.  
  117. >(Those who know about implementations of GCD, also know that 'round' produces
  118. >the GCD in the least number of iterations.)
  119.  
  120. >-----
  121.  
  122. >To summarize, the 'correct' mod is one that produces remainders that follow
  123. >the _divisor_, and therefore the 'correct' quotient is the _floor_ function.
  124. >If your language allows more than one, then the next one should be the
  125. >'round' function (& least absolute remainders).
  126.  
  127. >Unless you plan for your language to run on only one machine, make the
  128. >quotient and mod functions _well-defined_, so that portability is ensured.
  129.  
  130. >----
  131.  
  132. >You might find additional insight in the paper
  133.  
  134. >ftp://ftp.netcom.com/pub/hb/hbaker/Gaussian.html  (also .ps.Z)
  135.  
  136. >-- 
  137. >www/ftp directory:
  138. >ftp://ftp.netcom.com/pub/hb/hbaker/home.html
  139.  
  140. >Copyright (c) 1996 by Henry G. Baker.  All rights reserved.
  141. >** Warning: Due to its censorship, CompuServe and its subscribers **
  142. >** are expressly prohibited from storing or copying this document **
  143. >** in any form.                                                   **
  144.  
  145.  
  146. The 1990s: the Duh Decade
  147.  
  148.